/*
 * ClientProtocol.java
 *
 * Created on August 11, 2006, 12:36 AM
 *
 */
package org.letva.copie.subserver;

import org.letva.copie.common.message.*;
import java.awt.datatransfer.*;
import java.awt.*;
import org.letva.copie.common.exceptions.*;
import java.util.LinkedList;
import java.net.*;
import java.io.*;

/**
 * Protokol po kome SubServerThread-ovi rade sa porukama koje stignu. Poruke
 * (Message) moze stici od <B>MainServer</B>a, <B>SubServer</B> ili <B>Client</B>a.
 * Za svaku od njih postoji metoda sa kojom radi.
 * @author Vuk Nikolic
 */
public class SubServerProtocol {

	/** Creates a new instance of ClientProtocol */
	public SubServerProtocol(SubServer s) {
		mySubServer = s;
	}

	public Object messageFromMainServer(Object m) {
		Object reply = null;
		if (((Message) m).getInfo() instanceof java.util.LinkedList) {
			// poruka sadrzi HashMapu, sto znaci da je spisak subServera
			// i to se treba azurirati!
			Object messages = (((Message) m).getInfo());
			mySubServer.setActiveSubServers((LinkedList) messages);
		}

		if (((Message) m).getInfo() instanceof java.lang.String) {
			// ovde je ako trazi zahtev o PREBACIVANJIMA sto treba da uradim
		}
		return m;
	}

	public Object messageFromSubServer(Object m) {
		// ovde pogledaj sta hoce od tebe
		// ako je fajl, onda uzmi ono iz clipboarder-a
		// i salji FileInfo
		Transferable content = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(this);
		Object reply = null;
		try {
			String s = (String) content.getTransferData(DataFlavor.stringFlavor);
			reply = new Message("subServer", "subServer", s);
		} catch (IOException ex) {
			mySubServer.getMyWindow().setDialogException("Connection Error", "Problems with input/output operations");
			reply = new Message("subServer", "client", "IOExcpetion");
			((Message) reply).setType("system");
		} catch (UnsupportedFlavorException ex) {
			reply = new Message("subServer", "client", "UnSupportedFlavor");
			((Message) reply).setType("system");
		}

		return reply;
	}

	public Object messageFromClient(Object m) throws EndClientThreadException {
		System.out.println("Poruka od clienta: " + m);
		Object reply = new Message("subServer", "client", "poruka od subServera");
		if (m != null) {
			Message myMessage = (Message) m;
			if ((myMessage).getInfo() instanceof java.lang.String) {
				String clientMessage = ((String) myMessage.getInfo());
				if (clientMessage.equals("#list#")) {
					// u ovom slucaju vraca listu svih subServera
					reply = new Message("subServer", "client", (Object) mySubServer.getActiveSubServers());
				}
				if (clientMessage.contains("#pasteFrom#")) {
					mySubServer.writeLog("SubServerProtocol: Clients wants to Paste From: " + clientMessage);
					// poruka je oblika #pasteFrom#10.0.0.7#3333#
					String pasteFromIpPort = clientMessage.replaceAll("#pasteFrom#", "");
					// sad imamo samo ip#port# odosno 10.0.0.7#3333#
					String[] pasteFromParts = pasteFromIpPort.split("#");
					String subServerIp = pasteFromParts[0].replace("/", "");
					int subServerPort = Integer.parseInt(pasteFromParts[1]);

					Socket subServerSocket = null;
					ObjectOutput out = null;
					ObjectInput in = null;

					Object inputMessage = null;
					// POVEZIVANJE SA DRUGIM PODSERVEROM koji slusa preko
					// subServerListenera
					try {
						subServerSocket = new Socket(subServerIp, subServerPort);
						// out = new ObjectOutputStream(subServerSocket.getOutputStream());
						in = new ObjectInputStream(subServerSocket.getInputStream());
						mySubServer.writeLog("Receiving message to subserver: " + subServerSocket.getInetAddress().toString());
						reply = in.readObject();
						// upravo smo dobili poruku od drugog podservera!
						mySubServer.writeLog("Message received from subserver: " + subServerSocket.getInetAddress().toString());
						mySubServer.incNetworkOperations();

						// !!!! AKO JE DOSLO DO PREKIDA VEZE UPASCE U CATCH GRANU.
						// !!!! Treba da posaljem "karakteristican" odgovor klijentu
						// !!!! da on zna da je doslo do prekida veze.
					} catch (SocketException ex) {
						mySubServer.writeLog("SubServerProtocol: SocketException: " + ex);
						reply = new Message("subServer", "client", "SocketExcpetion");
						((Message) reply).setType("system");
						mySubServer.decNetworkOperations();
						mySubServer.getMyWindow().setDialogException("Connection Error", "Connection problems with subserver");
					} catch (UnknownHostException e) {
						mySubServer.writeLog("SubServerProtocol: SocketTimeoutException: " + e);
						reply = new Message("subServer", "client", "SocketTimeoutExcpetion");
						((Message) reply).setType("system");
						mySubServer.decNetworkOperations();
						mySubServer.getMyWindow().setDialogException("Connection Error", "Unknown host!");
					} catch (IOException ex) {
						mySubServer.writeLog("SubServerProtocol: IOException: " + ex);
						reply = new Message("subServer", "client", "IOExcpetion");
						mySubServer.decNetworkOperations();
						((Message) reply).setType("system");
						mySubServer.getMyWindow().setDialogException("Connection Error", "Problems with input/output operations");
					} catch (ClassNotFoundException ex) {
						mySubServer.writeLog("SubServerProtocol: ClassNotFoundException: " + ex);
						reply = new Message("subServer", "client", "ClassNotFound");
						((Message) reply).setType("system");
						mySubServer.decNetworkOperations();
						mySubServer.getMyWindow().setDialogException("Internal Error", "ClassNotFound");
					}
					// sad ide konekcija na drugi subserver
					// i od njega trazimo sadrzaj clipboarda
					// ako ne mozemo da se konektujemo obavestavamo klijenta

				}
			}
		}
		return reply;
	}

	public Object getClipboardContent() throws UnsupportedFlavorException, IOException {
		Clipboard myClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();

		Object reply = null;

		Transferable content = myClipboard.getContents(null);

		if (myClipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
			reply = (String) content.getTransferData(DataFlavor.stringFlavor);
			System.out.println("STRING!");
		} else if (myClipboard.isDataFlavorAvailable(DataFlavor.javaFileListFlavor)) {
			java.util.List l = (java.util.List) content.getTransferData(DataFlavor.javaFileListFlavor);

			System.out.println("FILE!");

			fileInfoList = new LinkedList();
			for (int i = 0; i < l.size(); i++) {
				File file = (File) l.get(i);
				insertFile(file);
			}

			reply = fileInfoList;
		} else {
			System.out.println("SubserverProstocol: unsupproted data flavor");
			throw new UnsupportedFlavorException(myClipboard.getAvailableDataFlavors()[0]);
		}

		return new Message("subserver", "subserver", reply);

	}

	private static byte[] getBytesFromFile(File file) throws IOException {
		InputStream is = new FileInputStream(file);

		// Get the size of the file
		long length = file.length();

		// Create the byte array to hold the data
		byte[] bytes = new byte[(int) length];

		is.read(bytes);

		is.close();
		return bytes;
	}

	public void insertFile(File file) throws IOException {
		String fileName = file.getName();
		//String filePath = file.getParent().replace(startDir, "");
		String filePath = file.getParent();
		byte[] bytes = null;
		if (file.isDirectory()) {

			FileInfo fi = new FileInfo(bytes, file);
			fileInfoList.add(fi);

			String[] filesString = file.list();
			for (int k = 0; k < filesString.length; k++) {
				//System.out.println(file.getPath()+file.separator+filesString[k]);
				File newFile = new File(file.getPath() + file.separator + filesString[k]);
				insertFile(newFile);
			}

		}
		if (file.isFile()) {
			bytes = getBytesFromFile(file);

			fileInfoList.add(new FileInfo(bytes, file));
			FileInfo fileInfo = (FileInfo) fileInfoList.getLast();
			System.out.println("Poslednji ubacen:" + fileInfo.getFile().getPath());
		}
	}
	private SubServer mySubServer = null;
	private LinkedList fileInfoList = new LinkedList();
}
